﻿// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
using System;

namespace System.ComponentModel.Composition
{
    /// <summary>
    ///     Provides methods for composing <see cref="ComposablePart"/> objects.
    /// </summary>
    public interface ICompositionService
    {
        /// <summary>
        ///     Gets a value indicating whether the composition service has a composition pending.
        /// </summary>
        /// <value>
        ///     <see langword="true"/> if the <see cref="ICompositionService"/> currently has
        ///     exported objects and <see cref="ComposablePart"/> objects that have not yet been
        ///     composed by a call to <see cref="Compose"/>; otherwise, <see langword="false"/>.
        /// </value>
        bool IsCompositionPending { get; }

        /// <summary>
        ///     Gets a value indicating whether the container is currently composing.
        /// </summary>
        /// <value>
        ///     <see langword="true"/> if the <see cref="CompositionContainer"/> is currently 
        ///     composing due to a call to <see cref="Compose"/>, otherwise, <see langword="false"/>.
        /// </value>
        bool IsComposing { get; }

        /// <summary>
        ///     Adds the specified composable part to the composition service.
        /// </summary>
        /// <param name="part">
        ///     The <see cref="ComposablePart"/> to add to the <see cref="ICompositionService"/>.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="part"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///     The <see cref="ICompositionService"/> has been disposed of.
        /// </exception>
        /// <remarks>
        ///     <para>
        ///         If <paramref name="part"/> is already in the <see cref="ICompositionService"/> 
        ///         then this method does nothing.
        ///     </para>
        ///     <para>
        ///         The <see cref="ComposablePart"/> is not composed, nor are its exports available 
        ///         until <see cref="Compose"/> is called.
        ///     </para>
        /// </remarks>
        void AddPart(ComposablePart part);

        /// <summary>
        ///     Composes the composition service.
        /// </summary>
        /// <exception cref="CompositionException">
        ///     An error occurred during composition. <see cref="CompositionException.Issues"/> will
        ///     contain a list of errors that occurred.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///     The <see cref="CompositionContainer"/> has been disposed of.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///     <see cref="Compose"/> was called again before composition had finished.
        /// </exception>
        /// <remarks>
        ///     <para>
        ///         You can use the <see cref="IsComposing"/> property to determine if the
        ///         <see cref="ICompositionService"/> is in the process of composing.
        ///     </para>
        /// </remarks>
        void Compose();

        /// <summary>
        ///     Removes the specified composable part from the composition service.
        /// </summary>
        /// <param name="part">
        ///     The <see cref="ComposablePart"/> to remove from the 
        ///     <see cref="ICompositionService"/>.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="part"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///     The <see cref="ICompositionService"/> has been disposed of.
        /// </exception>
        /// <remarks>
        ///     <para>
        ///         If <paramref name="part"/> is not in the <see cref="ICompositionService"/> then
        ///         this method does nothing.
        ///     </para>
        ///     <para>
        ///         The <see cref="ComposablePart"/> is not removed from the 
        ///         <see cref="ICompositionService"/> and its exports are still available until 
        ///         <see cref="Compose"/> is called.
        ///     </para>
        /// </remarks>
        void RemovePart(ComposablePart part);

        CompositionResult SatisfyImports(ComposablePart composablePart);
    }
}